void Machine::CPUReset(char *filename) {
	address = 0;
	pc = 0x200;
	
	resetReg(); // set registers to 0

	// load in the game
	ofstream *in; 
	in.open( "c:/INVADERS", "rb" );
	fread(&memory[0x200], 0xfff, 1, in);
	fclose(in);
}

void Machine::resetReg() {
	for(int i = 0; i < sizeof(reg); i++) {
		reg[i] = 0;
	}
}

short int Machine::getNextOpCode() {
   short int result = 0 ;
   result = memory[pc] ; // in example res is 0xAB
   result = result << 8 ; // shift 8 bits left. In our example res is 0xAB00
   result = result | memory[pc++]; // or with next address to combine to 0xABCD
   pc = pc + 2 ; 
   return res ;
}

void Machine::stack_push(short int) {

}

short int Machine::stack_pop() {
	return 0;
}

void Machine::decodeOpCode() {
	short int opcode = getNextOpCode();
	
	short int firstDigit = opcode & 0xF000;
	short int secondDigit = opcode & 0x0F00;
	short int secondFourthDigit = opcode & 0x0F0F;
	short int thirdFourthDigit = opcode & 0x00FF;
	
	switch(opcode & 0xF000) {
		case 0x0000:
			switch(opcode & 0x000F) {
				case 0x00E0: 
					OpCode_00E0(opcode); 
					break;
				case 0x00EE: 
					OpCode_00EE(opcode); 
					break;
				default: 
					OpCode_0NNN(opcode);
					break;
			}
			break;
			
		case 0x1000:
			OpCode_1NNN(opcode);
			break;
			
		case 0x2000:
			OpCode_2NNN(opcode);
			break;
			
		case 0x3000:
			OpCode_3XNN(opcode);
			break;
			
		case 0x4000:
			OpCode_4XNN(opcode);
			break;
			
		case 0x5000:
			OpCode_5XY0(opcode);
			break;
			
		case 0x6000:
			OpCode_6XNN(opcode);
			break;
			
		case 0x7000:
			OpCode_7XNN(opcode);
			break;
			
		case 0x8000:
			switch(opcode & 0x000F) {
				case 0x0000:
				case 0x0001:
				case 0x0002:
				case 0x0003:
				
			}
		case 0x9000:
			// 
		case 0xA000:
		case 0xB000:
		case 0xC000:
		case 0xD000:
		case 0xE000:
		case 0xF000:
		default: 
			cout << "No such opcode" << endl;
			break;
	}
	
	
	
	
}


void Machine::OpCode_0NNN(short int opcode) {
	
	// Calls RCA 1802 program at address NNN.

}

void Machine::OpCode_00E0(short int opcode) {
	// Clear the screen
	
	for(int i = 0; i < sizeof(*display); i++)
		*display[i] = 0;
	for(int i = 0; i < sizeof(**display); i++)
		**display[i] = 0;
	
}
void Machine::OpCode_00EE(short int opcode) {

	// Returns from a subroutine.
	
}
void Machine::OpCode_1NNN(short int opcode) {
	// Jumps to address NNN.
	pc = opcode & 0x0FFF; 
	
	/*
		For example, passed in parameter is 0001 1010 0011 1101
										  &	0000 1111 1111 1111
										------------------------
											0000 1010 0011 1101
		Will jump to address: 1010 0011 1101
	*/

}
void Machine::OpCode_2NNN(short int opcode) {

	// Calls subroutine at NNN.

}
void OpCode_3XNN(short int opcode) {
	
}
void OpCode_4XNN(short int opcode);
void OpCode_5XY0(short int opcode);
void OpCode_6XNN(short int opcode);
void OpCode_7XNN(short int opcode);
void OpCode_8XY0(short int opcode);
void OpCode_8XY1(short int opcode);
void OpCode_8XY2(short int opcode);
void OpCode_8XY3(short int opcode);
void OpCode_8XY4(short int opcode);
void OpCode_8XY5(short int opcode);
void OpCode_8XY6(short int opcode);
void OpCode_8XY7(short int opcode);
void OpCode_8XYE(short int opcode);
void OpCode_9XY0(short int opcode);
void OpCode_ANNN(short int opcode);
void OpCode_BNNN(short int opcode);
void OpCode_CXNN(short int opcode);
void OpCode_DYXN(short int opcode);
void OpCode_EX9E(short int opcode);
void OpCode_EXA1(short int opcode);
void OpCode_FX07(short int opcode);
void OpCode_FX0A(short int opcode);
void OpCode_FX15(short int opcode);
void OpCode_FX18(short int opcode);
void OpCode_FX1E(short int opcode);
void OpCode_FX29(short int opcode);
void OpCode_FX33(short int opcode);
void OpCode_FX55(short int opcode);
void OpCode_FX65(short int opcode);
